#pragma once

#include <iostream>
#include <atomic>

#include "SharedServer.hpp"


class ShmSharedPtr {
public:
    // 默认构造函数
    explicit ShmSharedPtr(void* ptr)
        : _ptr(ptr) {
        // 分配一个新的共享指针节点，并设置初始引用计数为1
        _node = SharedServer::GetInstance()->NewShmSharedPtrNode(ptr);
        _node->_count.store(1, std::memory_order_relaxed);
    }

    explicit ShmSharedPtr(ShmSharedPtrNode* node)
        :_node(node) {
        _ptr = ShmServiceManger::GetInstance()->GetShmPtr(node->manageBlock);
    }

    // 拷贝构造函数
    ShmSharedPtr(const ShmSharedPtr& other) {
        _ptr = other._ptr;
        _node = other._node;
        if (_node) {
            // 增加引用计数
            _node->_count.fetch_add(1, std::memory_order_relaxed);
        }
    }

    // 移动构造函数
    ShmSharedPtr(ShmSharedPtr&& other) noexcept {
        _ptr = other._ptr;
        _node = other._node;
        other._ptr = nullptr;
        other._node = nullptr;
    }

    // 拷贝赋值运算符
    ShmSharedPtr& operator=(const ShmSharedPtr& other) {
        if (this != &other) {
            release();  // 释放当前对象持有的资源
            _ptr = other._ptr;
            _node = other._node;
            if (_node) {
                // 增加引用计数
                _node->_count.fetch_add(1, std::memory_order_relaxed);
            }
        }
        return *this;
    }

    // 移动赋值运算符
    ShmSharedPtr& operator=(ShmSharedPtr&& other) noexcept {
        if (this != &other) {
            release();  // 释放当前对象持有的资源
            _ptr = other._ptr;
            _node = other._node;
            other._ptr = nullptr;
            other._node = nullptr;
        }
        return *this;
    }

    // 析构函数
    ~ShmSharedPtr() {
        release();  // 释放资源
    }

    // 获取托管的原始指针
    void*& Get() {
        return _ptr;
    }

public:
    // 将 SharedServer 声明为友元类
    friend class SharedServer;

private:
    // 释放当前对象持有的资源
    void release() {
        if (_node) {
            // 减少引用计数，如果计数为0，则释放资源
            if (_node->_count.fetch_sub(1, std::memory_order_relaxed) == 1) {
                SharedServer::GetInstance()->deallocate(_ptr);
                SharedServer::GetInstance()->deallocate(_node);
            }
        }
    }

private:

    ShmSharedPtrNode* _node = nullptr;  // 指向共享指针节点
    void* _ptr = nullptr;  // 原始指针
};